#pragma once
namespace graph_virtual
{
   namespace details
   {

   }

struct virtual_graph_view_t
{
   virtual_graph_view_t(virtual_graph_ptr_t graph)
      :  graph_(graph)
   {}
   virtual bool vertex_predicate(graph_basic::vertex_t& v) const =0;
   virtual bool edge_predicate(graph_basic::edge_t& e) const =0 ;
   virtual graph_basic::graph_view_ptr_t get_view_for_graph(graph_basic::graph_ptr_t graph) const =0;

   graph_basic::graph_int_t get_vertex_count(graph_basic::graph_id_t id) const;
   virtual_graph_t& get_graph();
   virtual_graph_t const & get_graph() const;
   virtual_graph_ptr_t get_graph_ptr();
   graph_basic::vertex_t& operator[](graph_basic::vertex_id_t id);
   graph_basic::vertex_t const & operator[](graph_basic::vertex_id_t id) const;
   graph_basic::vertex_t& get_vertex_by_id(graph_basic::vertex_id_t id);
   graph_basic::vertex_t const & get_vertex_by_id(graph_basic::vertex_id_t id) const;
private:
   virtual_graph_ptr_t graph_;
};

typedef boost::shared_ptr<virtual_graph_view_t> virtual_graph_view_ptr_t;
inline graph_basic::vertex_id_pair_t nearest_vertices(virtual_graph_view_t const & view, 
                                                         graph_basic::point_t first_p, graph_basic::point_t second_p);
struct all_way_view_t: virtual_graph_view_t
{
   all_way_view_t(virtual_graph_ptr_t graph)
      :  virtual_graph_view_t(graph)
    {}
   virtual bool vertex_predicate(graph_basic::vertex_t& v) const
   {
      return true;
   }

   virtual bool edge_predicate(graph_basic::edge_t& e) const
   {
      return true;
   }

   virtual graph_basic::graph_view_ptr_t get_view_for_graph(graph_basic::graph_ptr_t graph) const
   {
      return graph_basic::graph_view_ptr_t(new graph_basic::graph_all_way_view_t(graph));
   }
};


struct motor_way_view_t: virtual_graph_view_t
{
   virtual bool vertex_predicate(graph_basic::vertex_t& v) const
   {
      return true;
   }
   virtual bool edge_predicate(graph_basic::edge_t& e) const
   {
      if (e.get_highway() >=1 && e.get_highway() <= 9)
      return true;
      else
      return false;
   }
   virtual graph_basic::graph_view_ptr_t get_view_for_graph(graph_basic::graph_ptr_t graph) const
   {
      return graph_basic::graph_view_ptr_t(new graph_basic::graph_motor_way_view_t(graph));
   }
   
   motor_way_view_t(virtual_graph_ptr_t graph)
      :  virtual_graph_view_t(graph)
   {}
};
struct bicycle_way_view_t: virtual_graph_view_t
{
   virtual bool vertex_predicate(graph_basic::vertex_t& v) const
   {
      return true;
   }
   virtual bool edge_predicate(graph_basic::edge_t& e) const
   {
      if ( (e.get_highway() >=2 && e.get_highway() <= 9) ||
      (e.get_highway() == 11)||
      (e.get_highway() == 13))
         return true;
      else
         return false;
   }
   virtual graph_basic::graph_view_ptr_t get_view_for_graph(graph_basic::graph_ptr_t graph) const
   {
      return graph_basic::graph_view_ptr_t(new graph_basic::graph_bicycle_view_t(graph));
   }
   
   bicycle_way_view_t(virtual_graph_ptr_t graph)
      :  virtual_graph_view_t(graph)
      {}
};


struct foot_way_view_t: virtual_graph_view_t
{
   virtual bool vertex_predicate(graph_basic::vertex_t& v) const
   {
      return true;
   }
   virtual bool edge_predicate(graph_basic::edge_t& e) const
   {
      if ( (e.get_highway() >= 2 && e.get_highway() <= 11) ||
           (e.get_highway() == 14))
         return true;
      else
         return false;
   }
   virtual graph_basic::graph_view_ptr_t get_view_for_graph(graph_basic::graph_ptr_t graph) const
   {
      return graph_basic::graph_view_ptr_t(new graph_basic::graph_foot_way_view_t(graph));
   }
   
   foot_way_view_t(virtual_graph_ptr_t graph)
      :  virtual_graph_view_t(graph)
   {}
};

}